package com.sdp.right.excel.importExcel;


import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdp.core.bizc.exception.ApplicationException;
import com.sdp.core.bizc.exception.ExceptionMessage;
import com.sdp.core.bizc.vo.BusinessContext;
import com.sdp.core.bizc.vo.Result;
import com.sdp.right.db.sys_dict.service.ISysDictService;
import com.sdp.right.db.sys_import_template.service.ISysImportTemplateService;
import com.sdp.right.db.sys_import_template_detail.service.ISysImportTemplateDetailService;
import com.sdp.right.entity.SysImportTemplate;
import com.sdp.right.entity.SysImportTemplateDetail;
import com.sdp.right.utils.RightConstants;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/excel/ImportExcelControl")
public class ImportExcelControl {

	@Autowired
	private ISysImportTemplateService iSysImportTemplateService;
	
	@Autowired
	private ISysImportTemplateDetailService iSysImportTemplateDetailService;
	

	@Autowired
	private ApplicationContext applicationContext;

	@Autowired
	private ISysDictService iSysDictService;
	
	private int MAXCOUNT = 10000;

	
	/**
	 * 数据导入
	 * @param request
	 * @param response
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@PostMapping(value = "/excelImport")
	@Transactional(rollbackFor=Exception.class)
	public Result<?> excelImport(HttpServletRequest request, HttpServletResponse response) {

		BusinessContext businessContext = new BusinessContext();
		List<String> rowErrorMesList = new ArrayList<String>();
		businessContext.put("rowErrorMesList", rowErrorMesList);

		// 存放下拉信息
		Map<String, Map<String, String>> dictInfo = new HashMap<>();
		String templateId = request.getParameter("templateId");
		if (StringUtils.isEmpty(templateId)) {
			return Result.error("请指定导入的数据模板");
		}
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象

		if (StringUtils.isEmpty(mf)) {
			return Result.error("请先选择导入的EXCEL文件");
		}

		try {
			InputStream inputStream = mf.getInputStream();
			ResettableInputStream resettableStream = new ResettableInputStream(inputStream);
			
			if(getExcelRowCount(resettableStream, 1)>MAXCOUNT) {
				return Result.error("每次导入数据记录不能超过10000条");
			}
			// 重置流以复用
			resettableStream.reset();
			
			// 获取模板信息
			SysImportTemplate template = iSysImportTemplateService.querySysImportTemplateById(templateId);
			List<SysImportTemplateDetail> templateDetailList = iSysImportTemplateDetailService.querytemplateDetailByTemplateId(templateId,RightConstants.是.getCode());
			if (template == null || templateDetailList == null || templateDetailList.size() == 0) {
				return Result.error("模板信息不存在");
			}

			// 导入前的回调
			if (!StringUtils.isEmpty(template.getImportBeforeCallback())) {
				ImportExcelCallbackService beforeCallback = (ImportExcelCallbackService) applicationContext.getBean(Class.forName(template.getImportBeforeCallback()));
				BusinessContext beforeBusinessContext = beforeCallback.execute(request, response);
				if(!beforeBusinessContext.isSuccess()) {
					return Result.error(beforeBusinessContext.getMessage());
				}
			}
			//行回调函数
			ImportExcelRowCallbackService rowCallbackService = null;
			if (!StringUtils.isEmpty(template.getImportRowCallback())) {
				rowCallbackService = (ImportExcelRowCallbackService) applicationContext.getBean(Class.forName(template.getImportRowCallback()));
			}
			
			// 方法接口
			IService<T> serviceImpl = (IService<T>) applicationContext.getBean(Class.forName(template.getServiceClassName()));

			// 实体
			Class entityClass = Class.forName(template.getEntityClassName());

			
			ImportListener importListener = new ImportListener(entityClass, serviceImpl, templateDetailList, dictInfo,iSysDictService, rowCallbackService,businessContext);
			ExcelReader excelReader = EasyExcel.read(resettableStream, importListener).build();
			ReadSheet readSheet = EasyExcel.readSheet(0).headRowNumber(1).build();

			excelReader.read(readSheet);
			excelReader.finish();

			// 导入后的回调
			if (!StringUtils.isEmpty(template.getImportAfterCallback())) {
				ImportExcelCallbackService afterCallback = (ImportExcelCallbackService) applicationContext.getBean(Class.forName(template.getImportAfterCallback()));
				BusinessContext afterBusinessContext = afterCallback.execute(multipartRequest, response);
				if(!afterBusinessContext.isSuccess()) {
					throw new ApplicationException(afterBusinessContext.getMessage());
				}
			}
		} catch (Exception e) {
			log.error(ExceptionMessage.getExceptionMessage(e));
			throw new ApplicationException("数据导入失败，请确认数据合法化");
//			return Result.error("数据导入出现异常"+ExceptionMessage.getSubStrExceptionMessage(e));
		}
		if (!businessContext.isSuccess()) {
			return Result.error(businessContext.getMessage());
		}else{
			return Result.ok(rowErrorMesList);
		}
	}
	
	
	public int getExcelRowCount(InputStream excelStream, int dataStartRowIndex) {
	    RowCountListener listener = new RowCountListener(dataStartRowIndex); 
	    
	    ExcelReader excelReader = EasyExcel.read(excelStream, listener).build();
		ReadSheet readSheet = EasyExcel.readSheet(0).headRowNumber(0).build();
		excelReader.read(readSheet);
		excelReader.finish();
	    
	    return listener.getTotalRows();
	}
}
